package com.sharengo.sms;

import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Component
public class Sms {


    @Autowired
    private SmsProperties smsProperties;

    private String path = "/MWGate/wmgw.asmx/MongateSendSubmit";

    /**
     * POST方式，向不同手机号码发送相同的内容
     *
     * @param pszMobis   手机号码，用英文的,分开，最大1000个号码
     * @param pszMsg     短信内容最大350个字，一个英文字母和一个汉字都视为一个字
     * @param iMobiCount 手机号码个数
     * @return
     */
    public String sendSameContentPost(String pszMobis
            , String pszMsg, int iMobiCount) throws IOException {
        Map<String, String> params = makeParam(pszMobis, pszMsg, iMobiCount);
        String result = null;
        result = doPost(makeUri(smsProperties.getWbs().getIp()
                , smsProperties.getWbs().getPort()
                , smsProperties.getSame_content_path()), params);
        return checkAnswer(result);
    }

    /**
     * GET方式，向不同手机号码发送相同的内容
     *
     * @param pszMobis   手机号码，用英文的,分开，最大1000个号码
     * @param pszMsg     短信内容最大350个字，一个英文字母和一个汉字都视为一个字
     * @param iMobiCount 手机号码个数
     * @return
     */
    public String sendSameContentGet(String pszMobis
            , String pszMsg, int iMobiCount
    ) throws IOException {
        Map<String, String> params = makeParam(pszMobis, pszMsg, iMobiCount);
        String result = null;
        result = doGet(makeUri(params, smsProperties.getWbs().getIp()
                , smsProperties.getWbs().getPort(), smsProperties.getSame_content_path()));
        return checkAnswer(result);
    }

    /**
     * GET方式,向不同手机号码发送不同的内容
     *
     * @param messages 短信内容
     * @return
     */
    public String sendDiffContentGet(List<Message> messages) throws IOException {
        String result = null;
        HashMap<String, String> params = new HashMap<>();
        params.put("multixmt", getMultixmt(messages));
        params.put("userId",smsProperties.getUserId());
        params.put("password",smsProperties.getPassword());
        result = doGet(makeUri(params, smsProperties.getWbs().getIp()
                , smsProperties.getWbs().getPort(), smsProperties.getDiff_content_path()));
        return checkAnswer(result);
    }
    /**
     * POST 方式，向不同手机号码发送不同的内容
     *
     * @param messages 短信内容
     * @return
     */
    public String sendDiffContentPost(List<Message> messages) throws IOException {
        String result = null;
        HashMap<String, String> params = new HashMap<>();

        params.put("multixmt", getMultixmt(messages));
        params.put("userId",smsProperties.getUserId());
        params.put("password",smsProperties.getPassword());
        result=doPost(makeUri(smsProperties.getWbs().getIp()
                , smsProperties.getWbs().getPort()
                , smsProperties.getDiff_content_path()),params);
        return checkAnswer(result);
    }

    private String getMultixmt(List<Message> messages){
        StringBuilder multixmtBuilder = new StringBuilder();
        int size = messages.size() - 1;
        int i = 0;
        for (Message message : messages) {
            multixmtBuilder.append(message.toString());
            i++;
            if (i <= size)
                multixmtBuilder.append(",");
        }
        return multixmtBuilder.toString();
    }

    /**
     * @param pszMobis
     * @param pszMsg
     * @param iMobiCount
     * @return
     */
    private Map<String, String> makeParam(String pszMobis, String pszMsg, int iMobiCount) {
        HashMap<String, String> params = new HashMap<>();
        params.put("pszMobis", pszMobis);
        params.put("pszMsg", pszMsg);
        params.put("iMobiCount", iMobiCount + "");
        params.put("pszSubPort", "*");
        params.put("userId", smsProperties.getUserId());
        params.put("password", smsProperties.getPassword());
        return params;
    }

    private URI makeUri(Map<String, String> params, String ip
            , int port, String path) {
        URI uri = null;
        List<NameValuePair> nameValuePairs = new ArrayList<>();
        Iterator iterator = params.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry entry = (Map.Entry) iterator.next();
            NameValuePair nameValuePair = new BasicNameValuePair(entry.getKey().toString()
                    , entry.getValue().toString());
            nameValuePairs.add(nameValuePair);
        }
        try {
            uri = new URIBuilder().setScheme("http")
                    .setHost(ip)
                    .setPort(port)
                    .setPath(path)
                    .addParameters(nameValuePairs)
                    .build();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        return uri;
    }

    private URI makeUri(String ip
            , int port, String path) {
        URI uri = null;
        try {
            uri = new URIBuilder().setScheme("http")
                    .setHost(ip)
                    .setPort(port)
                    .setPath(path)
                    .build();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        return uri;
    }

    private String  checkAnswer(String result) {
        String  regex="\">.*<";
        Pattern pattern=Pattern.compile(regex);
        Matcher matcher=pattern.matcher(result);
        String code=null;
        if(matcher.find()){
            code=result.substring(matcher.start()+2,matcher.end()-1);
            switch (code){
                case "-1":
                    return "参数为空。信息、电话号码等有空指针，登录失败";
                case "-12":
                    return "有异常电话号码";
                case "-14":
                    return "实际号码数超过1000个";
                case "-999":
                    return "服务器内部错误";
                case "-10001":
                    return "用户登录不成功(账号不存在/停用/密码错误)";
                case "-10003":
                    return "用户余额不足";
                case "-10011":
                    return "信息内容超长";
                case "-10029":
                    return "此用户没有权限从此通道发送信息(用户没有绑定该性质" +
                            "的通道，比如：用户发了小灵通的号码)";
                case "-10030":
                    return "不能发送移动号码";
                case "-10031":
                    return "手机号码(段)非法";
                case "-10057":
                    return "IP受限";
                case "-10056":
                    return "连接数超限";
            }
            if(code.length()>=15&&code.length()<=25)
                return "success";
            else
                return "正则匹配结果："+code+" 返回结果："
                        +result+" 匹配长度不在15到25，所以无法识别是否正确";
        }else{
            return "返回的结果 ："+result;
        }
    }

    private String doGet(URI uri) throws IOException {
        String result = null;
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse httpResponse = null;
        try {
            httpClient = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet(uri);
            httpResponse = httpClient.execute(httpGet);
            result = EntityUtils.toString(httpResponse.getEntity());
            EntityUtils.consume(httpResponse.getEntity());
        } finally {
            try {
                if (httpResponse != null)
                    httpResponse.close();
                if (httpClient != null)
                    httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    private String doPost(URI uri, Map<String, String> params) throws IOException {
        String result = null;
        CloseableHttpResponse httpResponse = null;
        CloseableHttpClient httpClient = null;
        List<NameValuePair> nameValuePairs = new ArrayList<>();
        Iterator iterator = params.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry entry = (Map.Entry) iterator.next();
            NameValuePair nameValuePair = new BasicNameValuePair(entry.getKey().toString()
                    , entry.getValue().toString());
            nameValuePairs.add(nameValuePair);
        }
        try {
            HttpPost httpPost = new HttpPost(uri);
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8));
            httpClient = HttpClients.createDefault();
            httpResponse = httpClient.execute(httpPost);

            result = EntityUtils.toString(httpResponse.getEntity());
            EntityUtils.consume(httpResponse.getEntity());
        } finally {
            try {
                if (httpResponse != null)
                    httpResponse.close();
                if (httpClient != null)
                    httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;

    }


    public static String generateMsgId() {
        int max = 1999999999;
        int min = 999999999;
        Random random = new Random();
        int s1 = random.nextInt(max) % (max - min + 1) + min;
        int s2 = random.nextInt(max) % (max - min + 1) + min;
        String msgId = s1 + "" + s2;
        System.out.println(msgId);
        return msgId;
    }

    public SmsProperties getSmsProperties() {
        return smsProperties;
    }

    public void setSmsProperties(SmsProperties smsProperties) {
        this.smsProperties = smsProperties;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }
}
